Another use for the timer is to get a regular source of interrupts at a particular rate. The timer counts at a rate controlled by the system clock, which on the PICmicro development board can be a quartz crystal. Such crystals give a very reliable frequency, hence their use in digital clocks and watches. If we know the frequency of the crystal we can write a program which will keep accurate track of time.
Here is how the timing in the PICmicro works:
The crystal "ticks" at a particular frequency. In the case of the PICmicro E-Block this is 19.6608 MHz. (A MHz is a million cycles per second)
The PICmicro executes a single instruction every four clock cycles, and a clock pulse is produced every time an instruction is completed. This means that clock pulses are sent into the system at the rate of (crystal frequency)/4. This means that the clock going into the PICmicro is at the rate of 19.6608MHz/4 or 4.9152 MHz.
Before the clock pulses are used to trigger the timer counter they are sent through a pre-scaler. This a hardware divider which can be configured to divide the clock pulses coming in by a particular number.
In the case of the PICmicro the prescaler can be set to divide by 1 (i.e. no prescaler), 2, 4, 8, 16, 32, 64, 128 or 256. For the LED display (where the LEDs need to be on for a while so that we can see them) I used a prescaler value of 32. This means that the timer register is incremented at a 32th of the clock frequency. The counter is eight bit, which means that it will "wrap round" and cause an interrupt every 256 counts. This means that I will get interrupts at a rate of:
4915200 / (32 * 256) = 4915200 / 8192 = 600 per second.
This isn't quite the value of 200 I want, it's 3 times too many, but I can't increase the prescaler any more as then it'll be running too slow, so in the code I use a variable I call 'counter' to make sure that I only count every third interrupt.
In the code on the right I update a variable, called divisor, in the interrupt handler. When divisor reaches 20 I increment my main counter, which means that it will get updated 10 times a second. If you run Exercise 4.6 you will see a ticking PICmicro!
/* EX 4.6 Second Clock */
/* tenth of a second counter */
int count = 0 ;
/* interrupt counter */
int divisor = 0 ;
/* TMR0 Overflow handler */
void tmrHandler( void )
{
refresh () ;
/* update interrupt counter */
divisor++ ;
if ( divisor == 20 ) {
/* update count every */
/* every 10th of a */
/* second */
count++ ;
divisor = 0 ;
}
}
void main ( void )
{
setup_hardware () ;
while (1)
{
display_value ( count ) ;
}
}